package com.es;

import com.alibaba.fastjson.JSONObject;
import com.es.bean.Tender;
import org.apache.http.HttpHost;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.UpdateByQueryAction;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.index.reindex.UpdateByQueryRequestBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

public class ESTest {

    private static final String INDEX = "tender_test";
    private static final String INDEX_NAME = "tender_test";
    private static final String TYPE = "data";

    private static final String HOSTNAME = "192.168.0.71";
    private static final RestHighLevelClient client = getClient();
    private static final TransportClient transportClient = getTransportClient();

    public static RestHighLevelClient getClient(){
        RestClientBuilder builder = RestClient.builder(
                new HttpHost(HOSTNAME, 9200, "http")
        );
        RestHighLevelClient client = new RestHighLevelClient(builder);
        return client;
    }

    public static TransportClient getTransportClient(){
        try{
            TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
                    .addTransportAddress(new TransportAddress(InetAddress.getByName(HOSTNAME),9300));
            return client;
        }catch (UnknownHostException e){
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) throws IOException {
        //addIndex(client);
        //deleteById("CTx-738Bu8HGt75FY0K3");
        //updateById("CTx-738Bu8HGt75FY0K3");
        //updateByQuery("23");
        updateByQueryAction("23");
        //System.out.println(searchById("DTx-738Bu8HGt75FY0K3"));
        //List<Tender> tenders = searchList("国际");
        //List<Tender> tenders = searchListByPages("分析仪", 5, 10);
        //List<Tender> tenders = searchListByScrollPages("分析仪", "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAp2kFlh1eDNRcmpvUkVXVHJXSDMxV3BSdGcAAAAAAAKdphZYdXgzUXJqb1JFV1RyV0gzMVdwUnRnAAAAAAACnaUWWHV4M1Fyam9SRVdUcldIMzFXcFJ0Zw==", 10);
        //List<Tender> tenders = searchListByScrollPageWithHighLight("分析仪", null, 10);
        //tenders.stream().forEach(item -> System.out.println(item));
    }

    public static List<Tender> searchListByScrollPageWithHighLight(String keyword, String scrollId, int pageSize) throws IOException {
        SearchResponse response = null;
        if(Objects.nonNull(scrollId)){
            SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
            searchScrollRequest.scroll(TimeValue.timeValueMinutes(5));
            response = client.scroll(searchScrollRequest, RequestOptions.DEFAULT);
        }else{
            SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
            SearchSourceBuilder builder = new SearchSourceBuilder();
            builder.query(QueryBuilders.multiMatchQuery(keyword, "product_name","product_agency"));
            //设置高亮查询 初始化 高亮 builder
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            /*设置高亮的 字段*/
            highlightBuilder.field("product_name");
            /*设置高亮标签字段*/
            highlightBuilder.preTags("<font color='red'>");
            highlightBuilder.postTags("</font>");
            /*把高亮builder 设置到 查询 builder 里面*/
            builder.highlighter(highlightBuilder);
            builder.size(pageSize);
            searchRequest.source(builder);
            searchRequest.scroll(TimeValue.timeValueMinutes(5));
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        }
        SearchHit[] hits = response.getHits().getHits();
        System.out.println(response.getHits().getTotalHits());
        System.out.println(response.getScrollId());
        List<Tender> collect = Arrays.stream(hits).map(hit -> JSONObject.parseObject(hit.getSourceAsString(), Tender.class)).collect(Collectors.toList());
        for (SearchHit hit : hits) {
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField productName = highlightFields.get("product_name");
            if(Objects.nonNull(productName)){
                System.out.println(productName);
            }
        }
        client.close();
        return collect;
    }

    public static List<Tender> searchListByScrollPages(String keyword, String scrollId, int pageSize) throws IOException {
        SearchResponse response = null;
        if(Objects.nonNull(scrollId)){
            /*如果游标 id 不为空的话，直接按照 游标 获取数据*/
            SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
            /*设置游标id, 有效时间 5 分钟*/
            searchScrollRequest.scroll(TimeValue.timeValueMinutes(5));
            response = client.scroll(searchScrollRequest, RequestOptions.DEFAULT);
        }else{
            SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
            SearchSourceBuilder builder = new SearchSourceBuilder();
            builder.query(QueryBuilders.multiMatchQuery(keyword, "product_name","product_agency"));
            builder.size(pageSize);
            searchRequest.source(builder);
            searchRequest.scroll(TimeValue.timeValueMinutes(5));
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        }
        SearchHit[] hits = response.getHits().getHits();
        System.out.println(response.getHits().getTotalHits());
        System.out.println(response.getScrollId());
        List<Tender> collect = Arrays.stream(hits).map(hit -> JSONObject.parseObject(hit.getSourceAsString(), Tender.class)).collect(Collectors.toList());
        client.close();
        return collect;
    }

    public static List<Tender> searchListByPages(String keyword, int pageNo, int pageSize) throws IOException {
        /*构建查询请求*/
        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        /*构建查询条件 builder*/
        SearchSourceBuilder builder = new SearchSourceBuilder();
        /*构建 多字段 查询*/
        builder.query(QueryBuilders.multiMatchQuery(keyword, "product_name","product_agency"));
        /*设置分页 每页大小*/
        builder.size(pageSize);
        /*设置 分页 page no*/
        builder.from(pageNo > 1 ?(pageNo - 1) * pageSize : 0);
        /*把组装好的 查询builder 设置到 查询请求中*/
        searchRequest.source(builder);
        /*执行查询*/
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = response.getHits().getHits();
        List<Tender> collect = Arrays.stream(hits).map(hit -> JSONObject.parseObject(hit.getSourceAsString(), Tender.class)).collect(Collectors.toList());
        System.out.println(response.getHits().getTotalHits());
        client.close();
        return collect;
    }

    public static List<Tender>  searchList(String keyword) throws IOException {
        /*初始化查询请求*/
        SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
        /*初始化 构建 查询 builder*/
        SearchSourceBuilder builder = new SearchSourceBuilder();
        /*初始化 多字段 查询 builder*/
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, "product_agency");
        /*设置 查询 多字段查询*/
        builder.query(multiMatchQueryBuilder);
        /*把 构建好的 查询 封装到 查询请求中*/
        searchRequest.source(builder);
        /*执行查询*/
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = response.getHits().getHits();
        List<Tender> collect = Arrays.stream(hits).map(hit -> JSONObject.parseObject(hit.getSourceAsString(), Tender.class)).collect(Collectors.toList());
        client.close();
        return collect;
    }

    public static void deleteById(String id) throws IOException {
        /*初始化 get 请求*/
        GetRequest request = new GetRequest(INDEX_NAME, TYPE, id);
        /*判断是否存在数据，用 id 查询*/
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        if(exists){
            /*初始化 Delete 请求*/
            DeleteRequest deleteRequest = new DeleteRequest(INDEX_NAME, TYPE, id);
            /*执行 delete 操作*/
            client.delete(deleteRequest, RequestOptions.DEFAULT);
        }
        client.close();
    }

    public static void updateById(String id) throws IOException {
        /*初始化 get 请求*/
        GetRequest request = new GetRequest(INDEX_NAME, TYPE, id);
        /*判断是否存在*/
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        if(exists){
            /*初始化 Update 请求，按照 id更新*/
            UpdateRequest updateRequest = new UpdateRequest(INDEX_NAME, TYPE, id);
            /*组装 数据*/
            Tender tender = new Tender("鉴定药敏分析仪"
                    ,"四川国际招标有限责任公司"
                    ,"招标结果"
                    ,"100");
            updateRequest.doc(JSONObject.toJSONString(tender), XContentType.JSON);
            /*执行更新操作*/
            client.update(updateRequest, RequestOptions.DEFAULT);
        }
        client.close();
    }

    public static void updateByQuery(String typeId) throws IOException {
        /*构建根据查询条件更新内容操作*/
        UpdateByQueryRequest updateByQuery = new UpdateByQueryRequest();
        /*设置更新条件*/
        updateByQuery.setQuery(QueryBuilders.matchQuery("notice_type_id", typeId));
        /*设置更新 INDEX*/
        updateByQuery.indices(INDEX);
        /*文档类型，ES8 默认为 doc,不用设置*/
        updateByQuery.setDocTypes("data");
        /*设置更新脚本，下面表示更新文档中的 product_agency,和 product_name 字段，如果是多个字段，也可以更新多个字段*/
        updateByQuery.setScript(new Script("ctx._source['product_agency']='一二三集团';ctx._source['product_name']='抗敏药物'"));
        long updated = client.updateByQuery(updateByQuery, RequestOptions.DEFAULT).getUpdated();
        /*更新条数*/
        System.out.println("修改成功：" + updated);
        client.close();
    }


    /**
     * 如果ES是7之前的版本，可以用 TransportClient 客户端，7版本之后改为 RestHighLevelClient了
     */
    public static void updateByQueryAction(String typeId){
        /*利用 UpdateByQueryAction 来构建一个 UpdateByQueryRequestBuilder*/
        UpdateByQueryRequestBuilder builder = UpdateByQueryAction.INSTANCE.newRequestBuilder(transportClient);
        /*设置更新脚本*/
        Script script = new Script("ctx._source['product_agency']='三一集团';ctx._source['product_name']='抗老药物'");
        BulkByScrollResponse response = builder.source(INDEX)
                .script(script)
                .filter(QueryBuilders.matchQuery("notice_type_id", typeId))
                .abortOnVersionConflict(false).get();
        long updated = response.getUpdated();
        /*更新条数*/
        System.out.println("修改成功：" + updated);
        transportClient.close();
    }

    public static Tender searchById(String id) throws IOException {
        /*初始化 get  请求*/
        GetRequest request = new GetRequest(INDEX_NAME, TYPE, id);
        /*按照 ID 获取数据*/
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        Tender tender = JSONObject.parseObject(response.getSourceAsString(), Tender.class);
        client.close();
        return tender;
    }

    public static void addIndex(RestHighLevelClient client) throws IOException {
        /*初始化 查询请求操作，指定操作 index 名称*/
        IndexRequest indexRequest = new IndexRequest(INDEX_NAME);
        /*实例化数据*/
        Tender tender = new Tender("鉴定药敏分析仪"
                ,"四川国际招标有限责任公司"
                ,"招标结果"
                ,"5");
        String json = JSONObject.toJSONString(tender);
        /*设置 类型，7.x 不用设置，默认是 _doc*/
        indexRequest.type("data");
        /*数据转换成  json 添加进去*/
        indexRequest.source(json, XContentType.JSON);
        /*添加索引 */
        client.index(indexRequest, RequestOptions.DEFAULT);
        client.close();
    }


}
